#include <iostream>
using namespace std;

class A{
    protected:
        int value_a;
    public:
        A(){}
        A(int a):value_a(a){}
        ~A(){}
};

// 公共基类生成中间子类时 加 virtual 
class B:virtual public A{
    protected:
        int value_b;
    public:
        B(){}
        // 注意 虽然没有通过中间子类去初始化公共基类的成员
        // 但是 中间子类的构造函数的初始化表中依然需要调用 公共基类的构造函数
        // 因为中间子类实例化对象时 需要！！
        B(int a, int b):A(a), value_b(b){}
        ~B(){}
};

// 公共基类生成中间子类时 加 virtual 
class C:virtual public A{
    protected:
        int value_c;
    public:
        C(){}
        // 注意 虽然没有通过中间子类去初始化公共基类的成员
        // 但是 中间子类的构造函数的初始化表中依然需要调用 公共基类的构造函数
        // 因为中间子类实例化对象时 需要！！
        C(int a, int c):A(a), value_c(c){}
        ~C(){}
};

// 中间子类生成汇聚子类时 不加 virtual 
// 此时 汇聚子类的 构造函数的初始化表中需要显性的调用
// 公共基类的构造函数来完成 对公共基类继承过来的成员 的初始化
// 如果没有调用 默认会调用公共基类的无参构造函数
class D:public B, public C{
    private:
        int value_d;
    public:
        D(){}
        D(int a, int b, int c, int d):A(a), B(a, b), C(a, c), value_d(d){}
        ~D(){}
        void show(){
            cout << value_a << endl; // 这样 汇聚子类中就只有一份公共基类的成员了
                                    // 直接访问 就不报有歧义的错误了
            cout << value_b << endl;
            cout << value_c << endl;
            cout << value_d << endl;
        }
};

int main(int argc, const char *argv[]){
    D d1(10, 20, 30, 40);
    d1.show();
    return 0;
}